import * as vscode from 'vscode';
import { ApiClient } from '../utils/apiClient';

export class AgentChatPanel {
    public static currentPanel: AgentChatPanel | undefined;
    private static readonly viewType = 'ohAgentChat';

    private readonly panel: vscode.WebviewPanel;
    private disposables: vscode.Disposable[] = [];
    private conversationId: string | undefined;
    private apiClient: ApiClient;

    public static createOrShow(extensionUri: vscode.Uri, apiClient: ApiClient) {
        const column = vscode.window.activeTextEditor ? vscode.window.activeTextEditor.viewColumn : undefined;

        if (AgentChatPanel.currentPanel) {
            AgentChatPanel.currentPanel.panel.reveal(column);
            return;
        }

        const panel = vscode.window.createWebviewPanel(
            AgentChatPanel.viewType,
            'Agent 对话',
            column ?? vscode.ViewColumn.Two,
            {
                enableScripts: true,
                retainContextWhenHidden: true
            }
        );

        AgentChatPanel.currentPanel = new AgentChatPanel(panel, extensionUri, apiClient);
    }

    private constructor(panel: vscode.WebviewPanel, extensionUri: vscode.Uri, apiClient: ApiClient) {
        this.panel = panel;
        this.apiClient = apiClient;

        this.panel.webview.html = this.getHtml();

        this.panel.webview.onDidReceiveMessage(async (message) => {
            if (message.type === 'user-message') {
                const text: string = message.text || '';
                const editor = vscode.window.activeTextEditor;

                const context = editor ? {
                    filePath: editor.document.uri.fsPath,
                    code: editor.document.getText(),
                    cursorLine: editor.selection.active.line,
                    cursorColumn: editor.selection.active.character
                } : undefined;

                // 回退 REST（当Webview未连接WS时走REST）
                try {
                    const resp = await this.apiClient.agentChat(text, this.conversationId, context);
                    this.conversationId = resp.conversationId;
                    this.panel.webview.postMessage({ type: 'agent-reply', text: resp.reply });
                } catch (e: any) {
                    this.panel.webview.postMessage({ type: 'agent-reply', text: `错误: ${e?.message || e}` });
                }
            }
        }, undefined, this.disposables);

        this.panel.onDidDispose(() => this.dispose(), null, this.disposables);
    }

    public dispose() {
        AgentChatPanel.currentPanel = undefined;

        while (this.disposables.length) {
            const x = this.disposables.pop();
            if (x) {
                x.dispose();
            }
        }
    }

    private getHtml(): string {
        const nonce = getNonce();
        const wsUrl = vscode.workspace.getConfiguration('oh-yidian-tong').get<string>('agent.websocketUrl') || '';
        return `
<!DOCTYPE html>
<html lang="zh-CN">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="Content-Security-Policy" content="default-src 'none'; img-src https: data:; style-src 'unsafe-inline'; script-src 'nonce-${nonce}';">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Agent 对话</title>
  <style>
    body { font-family: var(--vscode-font-family); color: var(--vscode-foreground); background: var(--vscode-editor-background); margin: 0; padding: 0; }
    .container { display: flex; flex-direction: column; height: 100vh; }
    .messages { flex: 1; overflow-y: auto; padding: 12px; }
    .msg { margin: 8px 0; padding: 10px 12px; border-radius: 8px; max-width: 80%; white-space: pre-wrap; }
    .user { background: var(--vscode-editorHoverWidget-background); align-self: flex-end; }
    .agent { background: var(--vscode-input-background); align-self: flex-start; }
    .input { display: flex; padding: 8px; gap: 8px; border-top: 1px solid var(--vscode-editorWidget-border); }
    input[type=text] { flex: 1; padding: 8px; border: 1px solid var(--vscode-input-border); background: var(--vscode-input-background); color: var(--vscode-input-foreground); }
    button { padding: 6px 12px; }
  </style>
 </head>
 <body>
  <div class="container">
    <div id="messages" class="messages"></div>
    <div class="input">
      <input id="input" type="text" placeholder="输入问题，回车发送..." />
      <button id="send">发送</button>
    </div>
  </div>
  <script nonce="${nonce}">
    const vscode = acquireVsCodeApi();
    const WS_URL = ${JSON.stringify(wsUrl)};
    const $messages = document.getElementById('messages');
    const $input = document.getElementById('input');
    const $send = document.getElementById('send');
    let ws = undefined;
    if (WS_URL) {
      try {
        ws = new WebSocket(WS_URL);
        ws.onmessage = (ev) => {
          try {
            const msg = JSON.parse(ev.data);
            if (msg?.text) {
              append('agent', msg.text);
            }
          } catch {}
        };
      } catch (e) { /* ignore */ }
    }

    function append(type, text) {
      const div = document.createElement('div');
      div.className = 'msg ' + type;
      div.textContent = text;
      $messages.appendChild(div);
      $messages.scrollTop = $messages.scrollHeight;
    }

    function send() {
      const text = $input.value.trim();
      if (!text) return;
      append('user', text);
      if (ws && ws.readyState === 1) {
        ws.send(JSON.stringify({ type: 'chat', message: text }));
      } else {
        vscode.postMessage({ type: 'user-message', text });
      }
      $input.value = '';
    }

    $send.addEventListener('click', send);
    $input.addEventListener('keydown', (e) => { if (e.key === 'Enter') send(); });

    window.addEventListener('message', (event) => {
      const msg = event.data;
      if (msg.type === 'agent-reply') {
        append('agent', msg.text);
      }
    });
  </script>
 </body>
 </html>`;
    }
}

function getNonce() {
    let text = '';
    const possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    for (let i = 0; i < 32; i++) {
        text += possible.charAt(Math.floor(Math.random() * possible.length));
    }
    return text;
}


